
#include "nane/InputSystem/InputDeviceSystem.h"
#include "nane/InputSystem/InputDeviceSystemImpl_.h"
#include "nane/core/assert.h"
#include "nane/core/log.h"

namespace nane 
{
    ////////////////////////////////////////////////////////////////////////////////////////////////
    InputDeviceSystem::InputDeviceSystem()
        : SubSystem<IInputDeviceSystem>( new Implementation() )
        , m( static_cast<Implementation*>(SubSystem<IInputDeviceSystem>::m) )
    {
        
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    InputDeviceSystem::~InputDeviceSystem()
    {
        Shutdown();
        delete m;
        m = NULL;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void InputDeviceSystem::Shutdown()
    {
        if( m->interface != NULL )
        {
            ShutdownContext();
        }
        SubSystem<IInputDeviceSystem>::Shutdown();
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    EInputDevice InputDeviceSystem::GetDeviceType() const
    {
        NANE_ASSERT_RV( m->interface != NULL, "InputDeviceSystem must be initialized", EInputDevice::Unknown );
        return enum_cast<EInputDevice>(m->interface->GetDeviceType());
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    bool InputDeviceSystem::InitializeContext( IWindow::OSHandle _windowHandle )
    {
        NANE_ASSERT_RV( m->interface != NULL, "InputDeviceSystem must be initialized", false );
        NANE_ASSERT_RV( _windowHandle != NULL, "IWindow must be valid", false );
        
        if( m->windowHandle == _windowHandle )
        {
            return true;
        }
        else if( m->windowHandle != NULL )
        {
            LOG_ERROR("InputDeviceSystem context already initialized for different IWindow. You must shutdown it first");
            return false;
        }
        
        if( m->interface->InitializeContext(_windowHandle) == true )
        {
            m->windowHandle = _windowHandle;
            return true;
        }
     
        return false;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void InputDeviceSystem::ShutdownContext()
    {
        NANE_ASSERT_R( m->interface != NULL, "InputDeviceSystem must be initialized" );
        if( m->windowHandle != NULL )
        {
            m->windowHandle = NULL;
            m->interface->ShutdownContext();
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    InputEvent* InputDeviceSystem::Poll()
    {
        NANE_ASSERT_RV( m->interface != NULL, "InputDeviceSystem must be initialized", NULL );
        InputEvent* polledEvent = NULL;
        if( m->interface->Poll(&m->polledEvent.deviceNum, &m->polledEvent.axis, &m->polledEvent.value) == true )
        {
            polledEvent = &m->polledEvent;
        }
        return polledEvent;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
}   // namespace nane
